package com.hp.bon.logreverse;

import com.hp.bon.sgw.util.dcc.DccAvpHelper;
import com.hp.ocs.diameter.message.AVP;
import com.hp.ocs.diameter.message.AVP_Address;
import com.hp.ocs.diameter.message.AVP_Float32;
import com.hp.ocs.diameter.message.AVP_Float64;
import com.hp.ocs.diameter.message.AVP_Grouped;
import com.hp.ocs.diameter.message.AVP_Integer32;
import com.hp.ocs.diameter.message.AVP_Integer64;
import com.hp.ocs.diameter.message.AVP_OctetString;
import com.hp.ocs.diameter.message.AVP_Time;
import com.hp.ocs.diameter.message.AVP_UTF8String;
import com.hp.ocs.diameter.message.AVP_Unsigned32;
import com.hp.ocs.diameter.message.AVP_Unsigned64;
import com.hp.ocs.diameter.message.DictionaryManager;
import com.hp.ocs.diameter.message.InvalidAVPLengthException;
import com.hp.ocs.diameter.message.InvalidAddressTypeException;
import com.hp.ocs.diameter.message.Message;
import com.hp.ocs.diameter.message.dictionary.AvpType;
import java.net.InetAddress;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import org.dom4j.Element;
import org.dom4j.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExtractHelper
{
  private static final Logger LOG = LoggerFactory.getLogger(ExtractHelper.class);
  public static final Map<String, Integer> AVP_TYPE_MAP = new HashMap();

  static { AVP_TYPE_MAP.put("Integer32", Integer.valueOf(1));
    AVP_TYPE_MAP.put("Integer64", Integer.valueOf(2));
    AVP_TYPE_MAP.put("Unsigned32", Integer.valueOf(3));
    AVP_TYPE_MAP.put("Unsigned64", Integer.valueOf(4));
    AVP_TYPE_MAP.put("Float32", Integer.valueOf(5));
    AVP_TYPE_MAP.put("Float64", Integer.valueOf(6));
    AVP_TYPE_MAP.put("UTF8String", Integer.valueOf(7));
    AVP_TYPE_MAP.put("OctetString", Integer.valueOf(8));
    AVP_TYPE_MAP.put("Grouped", Integer.valueOf(9));
    AVP_TYPE_MAP.put("Address", Integer.valueOf(10));
    AVP_TYPE_MAP.put("Time", Integer.valueOf(11));
    AVP_TYPE_MAP.put("Enumerated", Integer.valueOf(12)); }

  public static String getXmlNodeValue(Element element, String path)
  {
    try {
      Node node = element.selectSingleNode(path);
      if (node != null)
        return node.getStringValue();
    }
    catch (Exception localException) {
    }
    return null;
  }

  public static String getAvpValue(Message msg, String avpPath, String avpType)
  {
    Integer type = (Integer)AVP_TYPE_MAP.get(avpType.trim());
    if (type == null) {
      LOG.warn(avpType.trim() + " is not a validate type.");
      return null;
    }
    AVP avp = getAVP(msg, avpPath);
    if (avp != null) {
      try
      {
        return DccAvpHelper.getAvpValue(type.intValue(), avp);
      } catch (InvalidAVPLengthException e) {
        e.printStackTrace();
      } catch (InvalidAddressTypeException e) {
        e.printStackTrace();
      }
    }
    return null;
  }

  private static AVP getAVP(Message msg, String path) {
    LinkedList avpPath = convertXPath2AvpPath(path);
    AVP parentAVP = null;
    AVP findAVP = null;
    try {
      for (Iterator it = avpPath.iterator(); it.hasNext(); ) {
        AvpType avpType = (AvpType)it.next();
        if (parentAVP == null)
          findAVP = msg.find(avpType.getCode(), avpType.getVendorId());
        else {
          findAVP = new AVP_Grouped(parentAVP).find(avpType.getCode(), avpType.getVendorId());
        }
        if (findAVP == null) {
          return null;
        }
        if (it.hasNext())
          parentAVP = new AVP_Grouped(findAVP);
        else
          return findAVP;
      }
    }
    catch (Exception e)
    {
      e.printStackTrace();
      return null;
    }
    LOG.info("cant find avp: " + path);
    return null;
  }

  private static LinkedList<AvpType> convertXPath2AvpPath(String xmlPath) {
    if (xmlPath == null) {
      return null;
    }
    String[] paths = xmlPath.split("\\/");
    LinkedList avpPath = new LinkedList();
    for (String s : paths) {
      if ((s != null) && (!s.equals("")))
      {
        AvpType avpType = DictionaryManager.getInstance().avpType(4, s);
        if (avpType == null) {
          LOG.warn("not find avpType:" + s);
          return null;
        }
        avpPath.add(avpType);
      }
    }
    return avpPath;
  }

  public static String getTableName(String tableName, String tableYYYYMM) {
    return tableName + "_" + tableYYYYMM;
  }

  public static String getAvpValueForSQL(int format, AVP avp) throws InvalidAVPLengthException, InvalidAddressTypeException {
    switch (format) {
    case 1:{
      AVP_Integer32 avpi = new AVP_Integer32(avp);
      int value = avpi.queryValue();
      return Integer.toString(value);
    }
    case 2:{
      AVP_Integer64 avpi = new AVP_Integer64(avp);
      long value = avpi.queryValue();
      return Long.toString(value);
    }
    case 3:{
      AVP_Unsigned32 avpi = new AVP_Unsigned32(avp);
      int value = avpi.queryValue();
      return Integer.toString(value);
    }
    case 4:{
      AVP_Unsigned64 avpi = new AVP_Unsigned64(avp);
      long value = avpi.queryValue();
      return Long.toString(value);
    }
    case 5:{
      AVP_Float32 avpi = new AVP_Float32(avp);
      return Float.toString(avpi.queryValue());}
    case 6:{
      AVP_Float64 avpi = new AVP_Float64(avp);
      return Double.toString(avpi.queryValue());}
    case 7:{
      AVP_UTF8String avpi = new AVP_UTF8String(avp);
      return "'" + avpi.queryValue() + "'";}
    case 8:{
      AVP_OctetString avpi = new AVP_OctetString(avp);
      return "'" + avpi.queryValueAsString() + "'";}
    case 9:
      return null;
    case 10:{
      AVP_Address avpi = new AVP_Address(avp);
      return "'" + avpi.queryAddress().toString() + "'";
    }
    case 11:{
      AVP_Time avpi = new AVP_Time(avp);
      return "'" + avpi.queryDate().toString() + "'";
    }
    case 12:{
      AVP_Integer32 avpi = new AVP_Integer32(avp);
      int i = avpi.queryValue();
      return Integer.toString(i);
    }
    default:
    	 return null;
    }
  }

  public static long parseTime(String timeStr, String format)
  {
    try {
      Date date = new SimpleDateFormat(format).parse(timeStr);
      return date.getTime();
    } catch (ParseException e) {
      e.printStackTrace();
    }return -1L;
  }
}